﻿using System;
using System.Threading;

namespace Sunny.Com;

/// <summary>
/// 串口信息统计类
/// </summary>
public class ComStatistics
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public ComStatistics()
    {
        _counter.Tick = v => { _flow = v; };
    }

    private long _bytesReceived;
    private long _bytesSent;
    private long _flow;
    private ValueCountTimer _counter = new() { Period = TimeSpan.FromSeconds(1) };

    /// <summary>
    /// 接收数据字节数
    /// </summary>
    public long BytesReceived => _bytesReceived;

    /// <summary>
    /// 发送数据字节数
    /// </summary>
    public long BytesSent => _bytesSent;

    /// <summary>
    /// 最后发送时间
    /// </summary>
    public DateTime LastSentTime { get; set; } = DateTime.MinValue;

    /// <summary>
    /// 最后接收时间
    /// </summary>
    public DateTime LastReceivedTime { get; set; } = DateTime.MinValue;

    /// <summary>
    /// 每秒流量（字节/秒）
    /// </summary>
    public long Flow => (DateTime.Now - LastSentTime) < TimeSpan.FromSeconds(2) || (DateTime.Now - LastReceivedTime) < TimeSpan.FromSeconds(2) ? _flow : 0;

    /// <summary>
    /// 每秒流量
    /// </summary>
    public string FlowString => ToFlowString(Flow);

    /// <summary>
    /// 增加接收数据字节数统计
    /// </summary>
    /// <param name="bytesCount">字节数</param>
    public void AddReceivedBytes(long bytesCount)
    {
        Interlocked.Add(ref _bytesReceived, bytesCount);
        LastReceivedTime = DateTime.Now;
        _counter.Add(bytesCount);
    }

    /// <summary>
    /// 增加发送数据字节数统计
    /// </summary>
    /// <param name="bytesCount">字节数</param>
    public void AddSentBytes(long bytesCount)
    {
        Interlocked.Add(ref _bytesSent, bytesCount);
        LastSentTime = DateTime.Now;
        _counter.Add(bytesCount);
    }

    /// <summary>
    /// 清除发送、接收字节数统计
    /// </summary>
    public void ClearStatistics()
    {
        Interlocked.Exchange(ref _bytesSent, 0);
        Interlocked.Exchange(ref _bytesReceived, 0);
        _counter.Add(0);
    }

    private static string ToFlowString(long flow)
    {
        if (flow < 1000) return $"{flow}B/s";
        if (flow < 1000 * 1000) return $"{(flow / 1024.0):F2}KB/s";
        if (flow < 1000 * 1000 * 1000) return $"{(flow / 1024.0 / 1024.0):F2}MB/s";
        return $"{flow}B/s";
    }

    /// <summary>
    /// 接收数据状态
    /// </summary>
    /// <param name="span">时间间隔</param>
    /// <returns>在指定时间间隔内是否接收到数据</returns>
    public bool ReceivedStatus(TimeSpan span) => DateTime.Now - LastReceivedTime < span;
}